package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.context.BaseContext;
import com.hmall.common.dto.Address;
import com.hmall.common.feign.AddressClientFeign;
import com.hmall.common.feign.ItemClientFeign;
import com.hmall.common.pojo.Item;
import com.hmall.order.mapper.OrderDetailMapper;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderInfo;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Date;

@Service
@Slf4j
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private OrderDetailMapper orderDetailMapper;
    @Resource
    private ItemClientFeign itemClientFeign;
    @Resource
    private AddressClientFeign addressClientFeign;
    @Resource
    private OrderLogisticsMapper orderLogisticsMapper;
    @Resource
    private RabbitTemplate rabbitTemplate;


    @Override
    @Transactional  //事务
    public Long submitMinus(OrderInfo orderInfo) {

        //- 1）根据雪花算法生成订单id
        //  1.1先创建订单对象
        Order order = new Order();
        //  1.2获取Userid
        Long userId = BaseContext.getCurrentId();
        System.out.println(userId);

        //- 2）商品微服务提供FeignClient，实现根据id查询商品的接口
        //- 3）根据itemId查询商品信息 并且需要对商品进行判断
        Item commodity = itemClientFeign.weight(orderInfo.getItemId());
        //  3.1并且需要对商品库存进行判断
        if (commodity.getStock() < orderInfo.getNum()){
            log.info("此商品库存不足");
            throw new RuntimeException("此商品库存不足");
        }
        //- 4）基于商品价格、购买数量计算商品总价：totalFee  购买数量 * 商品价格
        long totalFee = orderInfo.getNum() * commodity.getPrice();

        //- 5）封装Order对象，初识status为未支付
        order.setTotalFee(totalFee);        //需要付款的总金额
        order.setPaymentType(3);            //支付类型
        order.setUserId(userId);            //获取用户自己的id
        order.setStatus(1);                 //订单的状态
        order.setCreateTime(new Date());    //创建订单的时间
        order.setUpdateTime(new Date());    //更新时间

        //- 6）调用mapper将Order写入数据库tb_order表中
        orderMapper.insert(order);

        //- 7）将商品信息、orderId信息封装为OrderDetail(订单详情表)对象，写入tb_order_detail表
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(order.getId());   //订单编号
        orderDetail.setItemId(orderInfo.getItemId());  //商品ID
        orderDetail.setNum(orderInfo.getNum());
        orderDetail.setTitle(commodity.getName());
        orderDetail.setPrice(commodity.getPrice());
        orderDetail.setImage(commodity.getImage());
        orderDetail.setCreateTime(new Date());
        orderDetail.setUpdateTime(new Date());
        orderDetailMapper.insertDetail(orderDetail);

        //- 8）将user-service的根据id查询地址接口封装为FeignClient
        //- 9）根据addressId查询user-service服务，获取地址信息
        Address addressId = addressClientFeign.findAddressById(orderInfo.getAddressId());

        //- 10）将地址封装为OrderLogistics对象，写入tb_order_logistics表
        OrderLogistics orderLogistics = new OrderLogistics();
        orderLogistics.setOrderId(order.getId());  //订单编号
        orderLogistics.setContact(addressId.getContact());
        orderLogistics.setPhone(addressId.getMobile());
        orderLogistics.setProvince(addressId.getProvince());
        orderLogistics.setCity(addressId.getCity());
        orderLogistics.setTown(addressId.getTown());
        orderLogistics.setStreet(addressId.getStreet());
        orderLogistics.setCreateTime(new Date());
        orderLogistics.setUpdateTime(new Date());
        orderLogisticsMapper.insertOrderLog(orderLogistics);
        //- 11）在item-service提供减库存接口，并编写FeignClient  stockMinus(减少)  stockUp(恢复)
        //- 12）调用item-service的减库存接口
        itemClientFeign.updateStock(orderInfo.getItemId(),orderInfo.getNum());
        orderInfo.setId(order.getId());
        orderInfo.setStatus(order.getStatus());
        log.info("下单成功,订单单号:" + order.getId() + "下单时间:" + new Date());

        //处理超时信息
        Message message = MessageBuilder
                .withBody(order.getId().toString().getBytes(StandardCharsets.UTF_8))
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .setExpiration("10000")//延迟10秒
//                .setHeader("x-death",5000)
                .build();

        //消息ID,封装到Corr
        CorrelationData correlationData = new CorrelationData(order.getId().toString());
        //使用下单交换机和绑定的key 发送消息
        rabbitTemplate.convertAndSend("order.topic","order.create",message,correlationData);
        //打印
        log.info("消息发送成功");

        return order.getId();
    }


    /**
     * 修改订单状态
     * @param id
     * @param i
     */
    @Override
    public void updateStatus(Long id, Integer i) {
        orderMapper.updateByStatus(id,i);
    }

}
